﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Timers;
using System.Threading;
using LogLib;

namespace DeviceCommon
{
    public delegate bool DoWorkItem(string inParams, out string outParams);

    public delegate void WorkingDoneHandler(string outParams);

    public delegate void DoFailedHandler(string error);

    public delegate void DoTimeoutHandler(string error);

    /// <summary>
    /// 连续循环执行相同操作的一种工作模式
    /// 操作成功后立即返回；
    /// 不成功则Sleep(some ms)后继续执行;
    /// 该操作必须响应超时事件，超时后应立即结束任务
    /// </summary>
    public class Polling : IDisposable
    {
        /// <summary>
        /// 循环间隔时间
        /// </summary>
        protected int scanInterval = 1000;
        public int ScanInterval
        {
            get { return scanInterval; }
            set { scanInterval = value; }
        }

        /// <summary>
        /// 超时时间(ms)
        /// </summary>
        protected int timeoutMS = 10000;
        public int TimeoutMilliSecond
        {
            get { return timeoutMS; }
            set { timeoutMS = value; }
        }

        /// <summary>
        /// 任务取消标记
        /// </summary>
        private bool cancellToken = false;
        public bool CancellToken
        {
            get { return cancellToken; }
            set { cancellToken = value; }
        }

        /// <summary>
        /// 同步操作标记值
        /// </summary>
        protected int syncPoint = 0;

        // 标记当前读卡器是否已经被占用
        protected bool _isBusy = false;
        public bool IsBusy
        {
            get { return _isBusy; }
        }

        protected System.Timers.Timer _timer;

        protected Stopwatch _sw = new Stopwatch();

        private DoWorkItem onWorking = null;

        public event WorkingDoneHandler WorkingDone = null;
        protected void OnWorkingDone(string outParams)
        {
            if (WorkingDone != null)
            {
                WorkingDone(outParams);
            }
        }

        public event DoFailedHandler DoFailed = null;
        protected void OnDoFailed(string error)
        {
            if (DoFailed != null)
            {
                DoFailed(error);
            }
        }

        public event DoTimeoutHandler Timeout = null;
        protected void OnDoTimeout(string error)
        {
            if (Timeout != null)
            {
                Timeout(error);
            }
        }

        private string inParams = "";

        /// <summary>
        /// 标记当前循坏任务是否正在运行，
        /// 即检查定时器是否正在工作
        /// </summary>
        public bool Running
        {
            get
            {
                if (_timer != null)
                {
                    return _timer.Enabled;
                }
                return false;
            }
        }

        public Polling(DoWorkItem worker, string inParamString)
        {
            onWorking = worker;
            inParams = inParamString;
        }

        protected void InitTimer()
        {
            _timer = new System.Timers.Timer();
            _timer.Interval = ScanInterval;
            _timer.AutoReset = true;
            _timer.Elapsed += Timer_Elapsed;
        }

        public void Start(WorkingDoneHandler done)
        {
            if (_timer == null)
            {
                InitTimer();
            }
            if (!_timer.Enabled)
            {
                _timer.Start();
                _sw.Restart();
                WorkingDone = done;
            }
            else
            {
                //Log.WriteAsync("Timer 已经运行", "");
            }
        }

        public void Stop()
        {
            cancellToken = true;
            if (_timer == null)
            {
                return;
            }
            if (_timer.Enabled)
            {
                _timer.Stop();
            }
        }

        protected void Timer_Elapsed(object o, ElapsedEventArgs e)
        {
            if (_isBusy || cancellToken)
            {
                return;
            }
            string outParams = "";
            if (onWorking == null)
                return;
            if (OnWorking(out outParams))
            {
                cancellToken = true;
                OnWorkingDone(outParams);
                Stop();               
            }
            else
            {
                if (_sw.ElapsedMilliseconds >= TimeoutMilliSecond)
                {
                    string error = $"任务执行时间超时，已超过{TimeoutMilliSecond}ms未成功执行.";
                    Log.WriteAsync(error);
                    _sw.Stop();
                    Stop();
                }
                else
                {
                    OnDoFailed(outParams);
                }
            }
        }

        /// <summary>
        /// 循坏执行的单次操作
        /// </summary>
        /// <returns></returns>
        public bool OnWorking(out string outParams)
        {
            outParams = "";
            if (onWorking == null)
            {
                return false;
            }
            bool success = false;
            int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0);
            if (sync == 0)
            {
                try
                {
                    success = onWorking(inParams, out outParams);
                }
                catch (Exception ex)
                {
                    outParams = string.Format("读取身份证信息发生了异常.\n异常详情:{0}", ex.Message);
                    Log.WriteAsync(outParams);
                    Log.WriteException(ex.ToString());
                    //OnCatchException(DeviceAction.Working, ex);
                    return false;
                }
                finally
                {
                    syncPoint = 0;
                }               
            }
            else
            {
                outParams = "因上次动作未结束，动作不执行";
            }
            return success;          
        }

        public void Dispose()
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }
        }
    }
}
